package cn.edu.swu.miniwebsvr.handler;

import cn.edu.swu.miniwebsvr.core.Config;
import cn.edu.swu.miniwebsvr.core.Handler;
import cn.edu.swu.miniwebsvr.core.Parameter;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

public class DefaultHandler implements Handler {

    private static final Map<String, String> CONTENT_TYPE_MAP = new HashMap<>();

    static {
        // 常见文件类型的MIME类型映射
        CONTENT_TYPE_MAP.put("html", "text/html; charset=UTF-8");
        CONTENT_TYPE_MAP.put("htm", "text/html; charset=UTF-8");
        CONTENT_TYPE_MAP.put("css", "text/css; charset=UTF-8");
        CONTENT_TYPE_MAP.put("js", "application/javascript; charset=UTF-8");
        CONTENT_TYPE_MAP.put("json", "application/json; charset=UTF-8");
        CONTENT_TYPE_MAP.put("xml", "application/xml; charset=UTF-8");
        CONTENT_TYPE_MAP.put("txt", "text/plain; charset=UTF-8");
        CONTENT_TYPE_MAP.put("pdf", "application/pdf");
        CONTENT_TYPE_MAP.put("zip", "application/zip");
        CONTENT_TYPE_MAP.put("jpg", "image/jpeg");
        CONTENT_TYPE_MAP.put("jpeg", "image/jpeg");
        CONTENT_TYPE_MAP.put("png", "image/png");
        CONTENT_TYPE_MAP.put("gif", "image/gif");
        CONTENT_TYPE_MAP.put("ico", "image/x-icon");
        CONTENT_TYPE_MAP.put("svg", "image/svg+xml");
    }

    @Override
    public void handle(Parameter request, OutputStream response) {
        PrintWriter writer = new PrintWriter(response);

        try {
            String requestPath = request.getUrl();

            // 处理根路径，映射到index.html
            if ("/".equals(requestPath)) {
                requestPath = "/index.html";
            }

            // 移除开头的斜杠，构建相对路径
            String relativePath = requestPath.substring(1);

            // 获取webroot目录的路径 - 修复路径问题
            String webRootPath = Config.getInstance().getWebRoot();
            Path webRoot;

            // 先尝试相对路径（项目根目录下的webroot）
            webRoot = Paths.get(webRootPath).toAbsolutePath().normalize();

            // 如果相对路径不存在，尝试从类路径查找
            if (!Files.exists(webRoot)) {
                // 尝试在项目根目录下查找
                webRoot = Paths.get("").toAbsolutePath().resolve(webRootPath).normalize();
            }

            // 如果还是不存在，尝试从类路径查找（用于IDE环境）
            if (!Files.exists(webRoot)) {
                try {
                    // 获取类路径下的资源
                    URL resourceUrl = getClass().getClassLoader().getResource(webRootPath);
                    if (resourceUrl != null) {
                        webRoot = Paths.get(resourceUrl.toURI()).normalize();
                    }
                } catch (Exception e) {
                    System.err.println("无法从类路径找到webroot: " + e.getMessage());
                }
            }

            // 如果所有尝试都失败，使用当前工作目录
            if (!Files.exists(webRoot)) {
                webRoot = Paths.get(System.getProperty("user.dir"), webRootPath).normalize();
            }

            Path filePath = webRoot.resolve(relativePath).normalize();

            // 安全检查：确保请求的文件在webRoot目录内
            if (!filePath.startsWith(webRoot)) {
                System.err.println("DefaultHandler: 路径遍历攻击检测 - " + filePath);
                sendErrorResponse(403, "Forbidden - Directory traversal attempt detected", response);
                return;
            }

            System.out.println("DefaultHandler: WebRoot路径 - " + webRoot);
            System.out.println("DefaultHandler: 请求文件路径 - " + filePath);
            System.out.println("DefaultHandler: 文件是否存在 - " + Files.exists(filePath));
            if (Files.exists(filePath) && Files.isRegularFile(filePath) && Files.isReadable(filePath)) {
                byte[] fileBytes = Files.readAllBytes(filePath);

                // TODO: [222024321072047/李明燊] 确定并设置正确的 Content-Type (例如 text/html, image/jpeg 等)
                String contentType = determineContentType(filePath);

                // 获取文件最后修改时间
                String lastModified = Files.getLastModifiedTime(filePath)
                        .toInstant()
                        .atZone(ZoneId.systemDefault())
                        .format(DateTimeFormatter.RFC_1123_DATE_TIME);

                // 写入 200 OK 响应头
                writer.println("HTTP/1.1 200 OK");
                writer.println("Content-Type: " + contentType);
                writer.println("Content-Length: " + fileBytes.length);
                writer.println("Last-Modified: " + lastModified);
                writer.println("Connection: close");
                writer.println("Server: MiniWebSvr/1.0");

                // 根据文件类型决定缓存策略
                if (isStaticAsset(filePath)) {
                    writer.println("Cache-Control: public, max-age=3600"); // 静态资源缓存1小时
                } else {
                    writer.println("Cache-Control: no-cache");
                }

                writer.println(); // 空行分隔头部和主体
                writer.flush();

                // 写入文件内容
                response.write(fileBytes);

                System.out.println("DefaultHandler: 成功返回文件 - " + filePath.getFileName() + " (" + fileBytes.length + " bytes)");

            } else {
                // 文件不存在或路径错误，返回 404
                System.err.println("DefaultHandler: 文件未找到 - " + filePath);

                // 如果是根路径请求，尝试其他可能的默认文件
                if ("/index.html".equals(requestPath)) {
                    // 尝试其他可能的默认文件
                    String[] defaultFiles = {"index.htm", "default.html", "default.htm"};
                    for (String defaultFile : defaultFiles) {
                        Path altPath = webRoot.resolve(defaultFile);
                        if (Files.exists(altPath) && Files.isRegularFile(altPath) && Files.isReadable(altPath)) {
                            System.out.println("DefaultHandler: 找到替代默认文件 - " + altPath);
                            byte[] fileBytes = Files.readAllBytes(altPath);

                            writer.println("HTTP/1.1 200 OK");
                            writer.println("Content-Type: text/html; charset=UTF-8");
                            writer.println("Content-Length: " + fileBytes.length);
                            writer.println("Connection: close");
                            writer.println("Server: MiniWebSvr/1.0");
                            writer.println();
                            writer.flush();

                            response.write(fileBytes);
                            return;
                        }
                    }
                }

                sendNotFoundResponse(requestPath, response);
            }
        } catch (IOException e) {
            // TODO: [222024321072047/李明燊] 文件读取异常，返回 500 Internal Server Error
            System.err.println("DefaultHandler: 文件读取异常 - " + e.getMessage());
            e.printStackTrace();
            sendErrorResponse(500, "Internal Server Error - File Read Failed", response);
        } finally {
            try {
                response.flush();
            } catch (IOException e) {
                System.err.println("DefaultHandler: 刷新输出流异常 - " + e.getMessage());
            }
        }
    }

    /**
     * 根据文件扩展名确定Content-Type
     */
    private String determineContentType(Path filePath) {
        String fileName = filePath.getFileName().toString();
        int dotIndex = fileName.lastIndexOf('.');

        if (dotIndex > 0) {
            String extension = fileName.substring(dotIndex + 1).toLowerCase();
            String contentType = CONTENT_TYPE_MAP.get(extension);
            if (contentType != null) {
                return contentType;
            }
        }

        // 如果无法确定类型，使用系统探测的类型或默认类型
        try {
            String probedType = Files.probeContentType(filePath);
            return probedType != null ? probedType : "application/octet-stream";
        } catch (IOException e) {
            return "application/octet-stream";
        }
    }

    /**
     * 判断是否为静态资源文件（可以缓存）
     */
    private boolean isStaticAsset(Path filePath) {
        String fileName = filePath.getFileName().toString().toLowerCase();
        return fileName.endsWith(".css") || fileName.endsWith(".js") ||
                fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") ||
                fileName.endsWith(".png") || fileName.endsWith(".gif") ||
                fileName.endsWith(".ico") || fileName.endsWith(".svg");
    }

    /**
     * 发送404 Not Found响应
     */
    private void sendNotFoundResponse(String requestPath, OutputStream response) throws IOException {
        String htmlContent = "<!DOCTYPE html>\n" +
                "<html lang=\"zh-CN\">\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
                "    <title>404 Not Found - MiniWebSvr</title>\n" +
                "    <style>\n" +
                "        body {\n" +
                "            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n" +
                "            background: linear-gradient(135deg, #ff6b6b 0%, #feca57 100%);\n" +
                "            margin: 0;\n" +
                "            padding: 0;\n" +
                "            display: flex;\n" +
                "            justify-content: center;\n" +
                "            align-items: center;\n" +
                "            min-height: 100vh;\n" +
                "            color: #333;\n" +
                "        }\n" +
                "        .container {\n" +
                "            background: white;\n" +
                "            border-radius: 15px;\n" +
                "            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);\n" +
                "            padding: 40px;\n" +
                "            text-align: center;\n" +
                "            max-width: 500px;\n" +
                "            width: 90%;\n" +
                "        }\n" +
                "        h1 {\n" +
                "            color: #d63031;\n" +
                "            font-size: 48px;\n" +
                "            margin-bottom: 20px;\n" +
                "        }\n" +
                "        .error-code {\n" +
                "            font-size: 72px;\n" +
                "            font-weight: bold;\n" +
                "            color: #d63031;\n" +
                "            margin: 0;\n" +
                "        }\n" +
                "        .requested-path {\n" +
                "            background: #ffeaa7;\n" +
                "            padding: 10px;\n" +
                "            border-radius: 5px;\n" +
                "            margin: 20px 0;\n" +
                "            font-family: monospace;\n" +
                "        }\n" +
                "        .student-info {\n" +
                "            margin-top: 25px;\n" +
                "            padding-top: 20px;\n" +
                "            border-top: 1px solid #e2e8f0;\n" +
                "            color: #718096;\n" +
                "            font-size: 14px;\n" +
                "        }\n" +
                "    </style>\n" +
                "</head>\n" +
                "<body>\n" +
                "    <div class=\"container\">\n" +
                "        <div class=\"error-code\">404</div>\n" +
                "        <h1>页面未找到</h1>\n" +
                "        <p>抱歉，您请求的资源不存在。</p>\n" +
                "        <div class=\"requested-path\">\n" +
                "            <strong>请求路径:</strong> " + requestPath + "\n" +
                "        </div>\n" +
                "        <p>请检查URL是否正确，或返回<a href=\"/\">首页</a>。</p>\n" +
                "        \n" +
                "        <div class=\"student-info\">\n" +
                "            <p><strong>开发者信息</strong></p>\n" +
                "            <p>学号: 222024321072047 | 姓名: 李明燊</p>\n" +
                "            <p><strong>服务器:</strong> MiniWebSvr</p>\n" +
                "        </div>\n" +
                "    </div>\n" +
                "</body>\n" +
                "</html>";

        String httpResponse = "HTTP/1.1 404 Not Found\r\n" +
                "Content-Type: text/html; charset=UTF-8\r\n" +
                "Content-Length: " + htmlContent.getBytes("UTF-8").length + "\r\n" +
                "Connection: close\r\n" +
                "Server: MiniWebSvr/1.0\r\n" +
                "\r\n" +
                htmlContent;

        response.write(httpResponse.getBytes("UTF-8"));
    }

    /**
     * 发送通用错误响应
     */
    private void sendErrorResponse(int statusCode, String message, OutputStream response) {
        try {
            String statusText = getStatusText(statusCode);
            String htmlContent = "<!DOCTYPE html>\n" +
                    "<html>\n" +
                    "<head>\n" +
                    "<title>" + statusCode + " " + statusText + "</title>\n" +
                    "<style>\n" +
                    "body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }\n" +
                    "h1 { color: #d32f2f; }\n" +
                    ".container { max-width: 500px; margin: 0 auto; }\n" +
                    "</style>\n" +
                    "</head>\n" +
                    "<body>\n" +
                    "<div class='container'>\n" +
                    "<h1>" + statusCode + " - " + statusText + "</h1>\n" +
                    "<p>" + message + "</p>\n" +
                    "<hr>\n" +
                    "<p><small>MiniWebSvr - 222024321072047/李明燊</small></p>\n" +
                    "</div>\n" +
                    "</body>\n" +
                    "</html>";

            String httpResponse = "HTTP/1.1 " + statusCode + " " + statusText + "\r\n" +
                    "Content-Type: text/html; charset=UTF-8\r\n" +
                    "Content-Length: " + htmlContent.getBytes("UTF-8").length + "\r\n" +
                    "Connection: close\r\n" +
                    "Server: MiniWebSvr/1.0\r\n" +
                    "\r\n" +
                    htmlContent;

            response.write(httpResponse.getBytes("UTF-8"));
        } catch (IOException e) {
            System.err.println("发送错误响应失败: " + e.getMessage());
        }
    }

    /**
     * 获取HTTP状态码对应的文本描述
     */
    private String getStatusText(int statusCode) {
        switch (statusCode) {
            case 200: return "OK";
            case 403: return "Forbidden";
            case 404: return "Not Found";
            case 500: return "Internal Server Error";
            default: return "Unknown Status";
        }
    }
}